using System;
using System.Collections.Generic;
using System.Text;

namespace Fuzzy
{
    /// <summary>
    /// A fuzzy set where the membership function is constant (implemented as a PieceWiseLinearFuzzySet).
    /// </summary>
    public class ConstantValueFuzzySet:PieceWiseLinearFuzzySet
    {
        private double value;

        /// <summary>
        /// Creates a constant value fuzzy set.
        /// </summary>
        /// <param name="fuzzyLinguisticVariable">The linguistic variable where the set belongs to.</param>
        /// <param name="value">The constant value of the membership function.</param>
        public ConstantValueFuzzySet(FuzzyLinguisticVariable fuzzyLinguisticVariable, double value)
            : base(fuzzyLinguisticVariable,new double[]{(fuzzyLinguisticVariable.DomainMin+fuzzyLinguisticVariable.DomainMax)/2.0},new double[]{value})
        {
            this.value = value;
        }

        /// <summary>
        /// Creates a constant value fuzzy set.
        /// </summary>
        /// <param name="fuzzyLinguisticVariable">The linguistic variable where the set belongs to.</param>
        /// <param name="name">The name of the fuzzy set.</param>
        /// <param name="value">The constant value of the membership function.</param>
        public ConstantValueFuzzySet(FuzzyLinguisticVariable fuzzyLinguisticVariable, string name, double value)
            : base(fuzzyLinguisticVariable, name, new double[] { (fuzzyLinguisticVariable.DomainMin + fuzzyLinguisticVariable.DomainMax) / 2.0 }, new double[] { value })
        {
            this.value = value;
        }

        /// <summary>
        /// The membership function of the fuzzy set.
        /// </summary>
        /// <param name="x">The number of which membership we are interested in.</param>
        /// <returns>The membership of x. It returns the constant value have been given in the constructor if x in
        /// the domain of the fuzzy linguistic variable, otherwise 0.</returns>
        public override double Membership(double x)
        {
            if ((x <= fuzzyLinguisticVariable.DomainMin) || (x > fuzzyLinguisticVariable.DomainMax))
                return 0.0;
            else
                return value;
        }

        /// <summary>
        /// The alpha cut of the fuzzy set.
        /// </summary>
        /// <param name="alpha">The alpha value to which the alpha cut belongs.</param>
        /// <returns>An array consisting two-element double arrays with intervals (domainMin,domainMax or nothing depending on alpha). </returns>
        public override double[][] AlphaCut(double alpha)
        {
            if (alpha > value)
                return new double[0][];
            else
                return new double[][] { new double[] { fuzzyLinguisticVariable.DomainMin, fuzzyLinguisticVariable.DomainMax } };
        }

        /// <summary>
        /// The strict alpha cut of the fuzzy set.
        /// </summary>
        /// <param name="alpha">The alpha value to which the strict alpha cut belongs.</param>
        /// <returns>An array consisting two-element double arrays with intervals (domainMin,domainMax or nothing depending on alpha).</returns>
        public override double[][] StrictAlphaCut(double alpha)
        {
            if (alpha >= value)
                return new double[0][];
            else
                return new double[][] { new double[] { fuzzyLinguisticVariable.DomainMin, fuzzyLinguisticVariable.DomainMax } };
        }

        internal override FuzzySet Union(FuzzySet fuzzySet, bool mayRedirect)
        {
            if (value == 0.0)
                return fuzzySet;
            else if (value == 1.0)
                return new ConstantValueFuzzySet(fuzzyLinguisticVariable, 1.0);
            else 
                return base.Union(fuzzySet,mayRedirect);
                
        }

        internal override FuzzySet Intersection(FuzzySet fuzzySet, bool mayRedirect)
        {
            if (value == 1.0)
                return fuzzySet;
            else if (value == 0.0)
                return new ConstantValueFuzzySet(fuzzyLinguisticVariable, 0.0);
            else 
                return base.Intersection(fuzzySet, mayRedirect);

        }

        /// <summary>
        /// Computes the complement of the fuzzy set.
        /// </summary>
        /// <returns>The complement of the fuzzy set (a ConstantValueFuzzySet).</returns>
        public override FuzzySet Complement()
        {
            return new ConstantValueFuzzySet(fuzzyLinguisticVariable,1-value);
        }

        /// <summary>
        /// Returns the defuzzified value of the fuzzy set. (The defuzzification method is set in FuzzyUniverse.)
        /// </summary>
        /// <returns>The complement of the fuzzy set.</returns>
        public override double GetDefuzzifiedValue()
        {
            if (FuzzyUniverse.Defuzzification is COADefuzzification)
                return (fuzzyLinguisticVariable.DomainMax+fuzzyLinguisticVariable.DomainMin) / 2.0;
            else
                return base.GetDefuzzifiedValue();
        }

        /// <summary>
        /// Determines the supreme of the membership value of the fuzzy set. 
        /// </summary>
        /// <returns>The supreme of the membership value of the fuzzy set
        /// (the constant value of the membership function).</returns>
        public override double Sup()
        {
            return value;
        }

    }
}
